#pragma once
#include <iostream>
#include <mysql/mysql.h>
#include <json/json.h>
#include <sstream>
#include <iomanip>
#include <chrono>
#include <openssl/sha.h>
#include <queue>
#include <mysql/mysql_com.h>
#include <mutex>
#include <condition_variable>
#include <stdexcept>
#include <atomic>
#include <thread>
#include <unordered_set>
#include <algorithm>

class DBConnectionPool
{
public:
    static DBConnectionPool *getInstance();
    void initialize();
    MYSQL *getConnection();
    void releaseConnection(MYSQL *conn);
    ~DBConnectionPool();
private:
    DBConnectionPool();
    void _initialize(const std::string &host, const std::string &user,
                    const std::string &password, const std::string &db,
                    unsigned int port, unsigned int poolSize = 200);
    MYSQL *createConnectionWithRetry(int maxRetry = 5, int delayMs = 1000);
    MYSQL *recreateConnection(MYSQL *oldConn);
    void monitorConnections();
    std::queue<MYSQL *> connections_;
    std::vector<MYSQL *> allConnections_;
    std::unordered_set<MYSQL *> busy_;
    std::string host_, user_, password_, db_;
    unsigned int port_;
    unsigned int poolSize_;
    std::mutex mutex_;
    std::condition_variable cond_;
    std::atomic<bool> running_;
    std::thread monitorThread_;
};
class MySQLConnectionGuard {
public:
    MySQLConnectionGuard(MYSQL *conn);
    ~MySQLConnectionGuard();
private:
    MYSQL *conn_;
};
